package xml.validations;

import java.util.ArrayList;
import java.util.List;

import xml.uidElements.output.AbstractOutputDataItem;
import xml.uidElements.output.DataOutputElement;
import xml.uidElements.output.OutputDataItem;
import xml.uidElements.output.OutputDataItemSet;
import xml.uidElements.output.OutputStructure;
import xml.uidElements.output.AbstractOutputStructure;
import xml.uidElements.output.OutputStructureSet;

public class FinderOutputElements {

	public List<DataOutputElement> findOutput(String data) {

		if(data == null || data.replaceAll(" ", "").equals(""))
			return new ArrayList<DataOutputElement>();
		
		data = data.replaceAll(" ", "");

		List<DataOutputElement> l = new ArrayList<DataOutputElement>();
		
		boolean ehSet = false;  //NOVO
		int minCardinality = 0;  //NOVO
		int maxCardinality = 0;   //NOVO
		


		String s = "";
		for (int i = 0; i < data.length(); i++) {

			char a = data.charAt(i);
			String b = "" + a;
			if (b.equals(",")) {

				if (!s.equals("")) {
					AbstractOutputDataItem d;
					if (ehSet){
						d = new OutputDataItemSet(s);
						((OutputDataItemSet)d).setCardinality(minCardinality, maxCardinality);
					}
					else
						d = new OutputDataItem(s);
					
					l.add(d);
				}
				s = "";
				ehSet = false; //NOVO
				
			} else if (b.equals(":")) {

				AbstractOutputDataItem d;
				if (ehSet){
					d = new OutputDataItemSet(s);
					((OutputDataItemSet)d).setCardinality(minCardinality, maxCardinality);
				}
				else
					d = new OutputDataItem(s);
				
				i = findDomain(d, i, data);
				l.add(d);
				s = "";
				ehSet = false; //NOVO
				
				
			} else if (b.equals("(")) {

				AbstractOutputStructure st; 
				if (ehSet){
					st = new OutputStructureSet(s, "");
					((OutputStructureSet)st).setCardinality(minCardinality, maxCardinality);					
				}
				else
					st = new OutputStructure(s, "");
				
				i = findData(st, i, data);
				l.add(st);
				s = "";
				ehSet = false; //NOVO		

			} else if (b.equals(")")) {

					AbstractOutputDataItem d;
					if (ehSet){
						d = new OutputDataItemSet(s);
						((OutputDataItemSet)d).setCardinality(minCardinality, maxCardinality);
					}
					else 
						d = new OutputDataItem(s);
					l.add(d);
					s = "";
					ehSet = false; //NOVO

			} else {
				
				if (b.equals(".")){
					String cardinality = "" + data.charAt(i+1) + data.charAt(i+2);
					if (cardinality.equals("..")){
						i = i+2;
						ehSet = true; //NOVO
						minCardinality = 0;  //NOVO
						maxCardinality = -1;   //NOVO
			
						s = "";
						System.out.println("Entrou para ver a cardinalidade");
					}
					
				}

				else  {
					if (Character.isDigit(data.charAt(i))){

						ehSet = true; //NOVO

						//vai buscar a cardinalidade minima.
						String stringMinValue = "";
						while (Character.isDigit(data.charAt(i))){ 
							stringMinValue = stringMinValue + data.charAt(i);
							i++;
						}	
						i--;
						Integer minValue = Integer.parseInt(stringMinValue);
						minCardinality = minValue.intValue();
						
						//vai buscar a cardinalidade maxima. Se nao encontrar ".." , a cardinalidade maxima vai ser a minima tb.						
						String conjunto = "" + data.charAt(i+1) + data.charAt(i+2);
						if (conjunto.equals("..") && Character.isDigit(data.charAt(i+3)) ){
							i = i+3;
							String stringMaxValue = "";
							while (Character.isDigit(data.charAt(i))){ 
								stringMaxValue = stringMaxValue + data.charAt(i);
								i++;
							}	
							i--;
							Integer maxValue = Integer.parseInt(stringMaxValue);
							maxCardinality = maxValue.intValue();

						}
						else 						
							maxCardinality = minValue.intValue();   //NOVO

					}
				
				
					else {

						s = s + a;
					}
				}
			}

		}

		if (!s.equals("")) {
			OutputDataItem d = new OutputDataItem(s);
			l.add(d);
		}

		return l;
	}

	private int findData(AbstractOutputStructure st, int i, String data) {
		String s = "";
		int j;		
			
		boolean ehSetInTheStructure = false;  //NOVO
		int min = 0;  //NOVO
		int max = 0;   //NOVO

		for (j = i + 1; j < data.length(); j++) {
			char a = data.charAt(j);
			String b = "" + a;
			if (b.equals(")")) {
				if (!s.equals("")) {
					AbstractOutputDataItem d;
					if (ehSetInTheStructure){
						d = new OutputDataItemSet(s);
						((OutputDataItemSet)d).setCardinality(min, max);
					}
					else 
						d = new OutputDataItem(s);
					
					st.addDataOutput(d);
					ehSetInTheStructure = false; //NOVO
					
				}
				return j;
			} else if (b.equals(",")) {
				if (!s.equals("")) {
					AbstractOutputDataItem d;
					if (ehSetInTheStructure){
						d = new OutputDataItemSet(s);
						((OutputDataItemSet)d).setCardinality(min, max);
					}
					else 
						d = new OutputDataItem(s);
					
					st.addDataOutput(d);
					ehSetInTheStructure = false; //NOVO
				}
				s = "";
			} else if (b.equals(":")) {

				AbstractOutputDataItem d;
				if (ehSetInTheStructure){
					d = new OutputDataItemSet(s);
					((OutputDataItemSet)d).setCardinality(min, max);
				}
				else 
					d = new OutputDataItem(s);
				
				j = findDomain(d, j, data);
				st.addDataOutput(d);
				ehSetInTheStructure = false; //NOVO				
				s = "";
			} else if (b.equals("(")) {

				AbstractOutputStructure struct;
				if (ehSetInTheStructure){
					struct = new OutputStructureSet(s, "");
					((OutputStructureSet)struct).setCardinality(min, max);
				}
				else
					struct = new OutputStructure(s, "");

				j = findData(struct, j, data);
				st.addDataOutput(struct);
				ehSetInTheStructure = false; //NOVO
				s = "";			
				
				
			} else {

				if (b.equals(".")){
					String cardinality = "" + data.charAt(j+1) + data.charAt(j+2);
					if (cardinality.equals("..")){
						j = j+2;
						ehSetInTheStructure = true; //NOVO
						min = 0;  //NOVO
						max = -1;   //NOVO
			
						s = "";
						System.out.println("Entrou para ver a cardinalidade no outro nivel");
					}
					
				}
				
				else {

					if (Character.isDigit(data.charAt(j))){

						ehSetInTheStructure = true; //NOVO

						//vai buscar a cardinalidade minima.
						String stringMinValue = "";
						while (Character.isDigit(data.charAt(j))){ 
							stringMinValue = stringMinValue + data.charAt(j);
							j++;
						}	
						j--;
						Integer minValue = Integer.parseInt(stringMinValue);
						min = minValue.intValue();
						
						//vai buscar a cardinalidade maxima. Se nao encontrar ".." , a cardinalidade maxima vai ser a minima tb.						
						String conjunto = "" + data.charAt(j+1) + data.charAt(j+2);
						if (conjunto.equals("..") && Character.isDigit(data.charAt(j+3)) ){
							j = j+3;
							String stringMaxValue = "";
							while (Character.isDigit(data.charAt(j))){ 
								stringMaxValue = stringMaxValue + data.charAt(j);
								j++;
							}	
							j--;
							Integer maxValue = Integer.parseInt(stringMaxValue);
							max = maxValue.intValue();

						}
						else 						
							max = minValue.intValue();   //NOVO

					}
					
					else

						s = s + a;
				}
			}

		}
		if (!s.equals("")) {
			OutputDataItem d = new OutputDataItem(s);
			st.addDataOutput(d);
		}
		return j;
	}
	

	private int findDomain(AbstractOutputDataItem d, int i, String data) {
		String s = "";
		int j;
		for (j = i + 1; j < data.length(); j++) {
			char a = data.charAt(j);
			String b = "" + a;
			if (b.equals(")")) {
				if (!s.equals(""))
					d.setDomain(s);
				return j - 1;
			} else if (b.equals(",")) {
				if (!s.equals(""))
					d.setDomain(s);
				return j;
			}
			s = s + b;

		}

		if (!s.equals("")) {
			d.setDomain(s);
		}

		return j;
	}

}
